package com.easy.common.util.auth;
import java.io.IOException;
import java.security.*;
import java.util.Arrays;
import javax.crypto.Cipher;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import com.easy.common.constant.Const;
import com.easy.common.constant.SysProps;
import com.easy.common.exception.InvalidPasswordException;
import com.easy.common.util.SecurityUtility;
import com.easy.common.util.auth.Authenticator;

public class Authenticator {
	public Authenticator()
	{
	}
	public static byte[] encrypt(int saltLength, byte passWord[])
	throws InvalidPasswordException, NoSuchAlgorithmException
	{
		byte rtArray[] = (byte[])null;
		byte salt[] = new byte[saltLength];
		byte digest[] = (byte[])null;
		if (passWord == null)
			throw new InvalidPasswordException("common.error.nullpassword");
		SecureRandom random = new SecureRandom();
		random.nextBytes(salt);
		MessageDigest md = null;
		try
		{
			md = MessageDigest.getInstance("MD5");
		}
		catch (NoSuchAlgorithmException ex)
		{
			throw ex;
		}
		md.update(salt);
		md.update(passWord);
		digest = md.digest();
		rtArray = new byte[salt.length + digest.length];
		System.arraycopy(salt, 0, rtArray, 0, salt.length);
		System.arraycopy(digest, 0, rtArray, salt.length, digest.length);
		return rtArray;
	}
	
	public static boolean isValidPassword(String inputPass, String savedPass)
		throws InvalidPasswordException, NoSuchAlgorithmException, IOException
	{
		return isValidPassword(SysProps.getInt("saltLength"), inputPass.getBytes(Const.DEFAULT_CODE), (new BASE64Decoder()).decodeBuffer(savedPass));
	}
	
	public static boolean isValidPassword(byte inputPass[], byte savedPass[])
		throws InvalidPasswordException, NoSuchAlgorithmException
	{
		return isValidPassword(SysProps.getInt("saltLength"), inputPass, savedPass);
	}
	
	public static boolean isValidPassword(int saltLength, byte inputPass[], byte savedPass[])
		throws InvalidPasswordException, NoSuchAlgorithmException
	{
		if (savedPass == null || savedPass.length < saltLength)
			throw new InvalidPasswordException("common.errors.savedPsssInvalid");
		byte salt[] = new byte[saltLength];
		
		System.arraycopy(savedPass, 0, salt, 0, saltLength);
		
		MessageDigest md = null;
		try
		{
			md = MessageDigest.getInstance("MD5");
		}
		catch (NoSuchAlgorithmException ex)
		{
			throw ex;
		}
		md.update(salt);
		md.update(inputPass);
		
		byte inputDigest[] = md.digest();
		byte savedPassDigest[] = new byte[savedPass.length - saltLength];
		System.arraycopy(savedPass, saltLength, savedPassDigest, 0, savedPass.length - saltLength);
		return Arrays.equals(inputDigest, savedPassDigest);
	}
	
	public static String encryptBase64(int saltLength, byte passWord[])
		throws Exception
	{
		return (new BASE64Encoder()).encode(encrypt(saltLength, passWord));
	}
	
	public static String encryptBase64(int saltLength, String passWord)
		throws Exception
	{
		return (new BASE64Encoder()).encode(encrypt(saltLength, passWord.getBytes(Const.DEFAULT_CODE)));
	}
	
	public static boolean isValidPasswordBase64(int saltLength, String inputPassStr, String savedPassStr)
		throws Exception
	{
		byte inputPass[] = inputPassStr.getBytes(Const.DEFAULT_CODE);
		byte savedPass[] = (new BASE64Decoder()).decodeBuffer(savedPassStr);
		return isValidPassword(saltLength, inputPass, savedPass);
	}
	
	public static boolean isValidRegist(int saltLength, String inputPassStr, String savedPassStr)
		throws Exception
	{
		if (saltLength < 2)
			saltLength = 10;
		byte inputPass[] = inputPassStr.getBytes(Const.DEFAULT_CODE);
		byte savedPass[] = (new BASE64Decoder()).decodeBuffer(savedPassStr);
		return isValidPassword(saltLength - 2, inputPass, savedPass);
	}
	
	public static boolean isValidRegist(String inputPassStr, String savedPassStr)
		throws Exception
	{
		return isValidRegist(SysProps.getInt("saltLength"), inputPassStr, savedPassStr);
	}
	
	public static byte[] ciphEncryptBytes(String srcStr)
		throws Exception
	{
		Cipher cipher = SecurityUtility.getPassWordCipher(1);
		byte bufBytes[] = srcStr.getBytes(Const.DEFAULT_CODE);
		return cipher.doFinal(bufBytes);
	}
	
	public static String ciphDecryptBytes(byte bufBytes[])
		throws Exception
	{
		Cipher cipher = SecurityUtility.getPassWordCipher(2);
		return new String(cipher.doFinal(bufBytes), Const.DEFAULT_CODE);
	}
	
	public static String ciphEncryptStr(String srcPass)
		throws Exception
	{
		Cipher cipher = SecurityUtility.getPassWordCipher(1);
		byte []passBytes = srcPass.getBytes(Const.DEFAULT_CODE);
		passBytes = cipher.doFinal(passBytes);
		return (new BASE64Encoder()).encode(passBytes);
	}
	
	public static String ciphDecryptStr(String encryptPass)
		throws Exception
	{
		try{
			Cipher cipher = SecurityUtility.getPassWordCipher(2);
			byte[] passBytes = new BASE64Decoder().decodeBuffer(encryptPass);
			passBytes = cipher.doFinal(passBytes);
			return new String(passBytes, Const.DEFAULT_CODE);
		}
		catch(Exception ex){
		}
		return encryptPass;
	}
}
